﻿using NexTrackDesktop.ViewModels;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using NexTrackDesktop.Media;
using System.Windows.Input;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using NexTrackDesktop.NexTrack;
using Moq;
using System.Linq;

namespace NexTrackDesktopTest
{
    
    
    /// <summary>
    ///This is a test class for MediaLibraryViewModelTest and is intended
    ///to contain all MediaLibraryViewModelTest Unit Tests
    ///</summary>
    [TestClass()]
    public class MediaLibraryViewModelTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //

        #endregion
        

        /// <summary>
        ///A test for MediaLibraryViewModel Constructor
        ///</summary>
        [TestMethod()]
        public void MediaLibraryViewModelConstructorTest()
        {
            //Mock a library with one song
            var testSongs = new List<Song>();
            testSongs.Add(new Song() { Album = "TestA", Title = "TestTitle" });

            var target = ConstructViewModelAndInjectLibrary(testSongs);

            //Ensure the target viewmodel has only the single song.
            Assert.AreEqual(1, target.Songs.Count);
            Assert.AreEqual(testSongs[0], target.Songs[0].Song);
        }

        private static Mock<ILibrary> MockLibrary(List<Song> testSongs = null)
        {
            var mockLibrary = new Mock<ILibrary>();
            mockLibrary.Setup(m => m.Items).Returns(new ReadOnlyCollection<Song>(testSongs ?? new List<Song>()));

            return mockLibrary;
        }

        private static MediaLibraryViewModel_Accessor ConstructViewModelAndInjectLibrary(List<Song> testSongs = null)
        {
            var mockLibrary = MockLibrary(testSongs);

            var mockClient = new Mock<IClient>();
            mockClient.Setup(m => m.MediaLibrary).Returns(mockLibrary.Object);

            //Inject the Mock
            ViewModelBase.Client = mockClient.Object;

            // Create the ViewModel
            return new MediaLibraryViewModel_Accessor();
        }

        /// <summary>
        ///A test for addFolder
        ///</summary>
        [TestMethod()]
        [DeploymentItem("NexTrackDesktop.exe")]
        public void addFolderTest()
        {
            var target = ConstructViewModelAndInjectLibrary();
            //target.addFolder()
            //TODO: Fix Dependency on FileBrowserDialog. It makes this hard to test.
            Assert.Inconclusive();
        }

        /// <summary>
        ///A test for addMedia
        ///</summary>
        [TestMethod()]
        [DeploymentItem("NexTrackDesktop.exe")]
        public void addMediaTest()
        {
            //TODO: Fix Dependency on FileBrowserDialog. It makes this hard to test.
            Assert.Inconclusive();
        }

        /// <summary>
        ///A test for addToPlaylist
        ///</summary>
        [TestMethod()]
        [DeploymentItem("NexTrackDesktop.exe")]
        public void addToPlaylistTest()
        {
            List<Song> TestSongs = new List<Song>() {
                new Song() { Title = "Song 1"},
                new Song() { Title = "Song 2"}
            };

            var mLib = MockLibrary(TestSongs);
            var mWebService = new Mock<MainServiceAdapter>();

            IParty tParty = new Party("0", "TestParty", "0", mWebService.Object);

            var mClient = new Mock<IClient>();
            mClient.Setup(m => m.MediaLibrary).Returns(mLib.Object);
            mClient.Setup(m => m.Party).Returns(tParty);

            ViewModelBase.Client = mClient.Object;

            var target = new MediaLibraryViewModel_Accessor();

            //Select both songs
            target.Songs[0].Selected = true;
            target.Songs[1].Selected = true;

            //Add the selected songs to the playlist
            target.addToPlaylist();

            //Check the playlist for these songs.
            Assert.AreEqual(2, tParty.Playlist.Items.Count);
            Assert.AreEqual(TestSongs[0], tParty.Playlist.Items[0]);
            Assert.AreEqual(TestSongs[1], tParty.Playlist.Items[1]);
        }

        /// <summary>
        ///A test for SelectedSongs
        ///</summary>
        [TestMethod()]
        public void SelectedSongsTest()
        {
            List<Song> testSongs = new List<Song>() {
                new Song() { Title = "Song 0"},
                new Song() { Title = "Song 1"},
                new Song() { Title = "Song 2"},
                new Song() { Title = "Song 3"},
                new Song() { Title = "Song 4"}
            };

            var target = ConstructViewModelAndInjectLibrary(testSongs);

            //test selection of songs, selecting songs 0, 3, and 4.
            target.Songs[0].Selected = true;
            target.Songs[3].Selected = true;
            target.Songs[4].Selected = true;

            //the SelectedSongs property executes code to select songs.
            var selectedSongs = target.SelectedSongs.Select(s => s.Song);

            //test against the songs that are expected
            Song[] expecteds = { testSongs[0], testSongs[3], testSongs[4] };
            Util.AssertAllEqual(expecteds, selectedSongs);
        }
    }
}
